﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace InnovTech.Data.Dynamic
{
    public class DynamicObject : IDynamicObject
    {

        private Dictionary<string, IDynamicObjectMember> _members;
        protected Dictionary<string, IDynamicObjectMember> Members
        {
            get { if (_members == null) _members = new Dictionary<string, IDynamicObjectMember>(); return _members; }
        }

        public IDynamicObjectMember this[string key]
        {
            get
            {
                return Members[key];
            }
            set
            {
                if (value == null)
                    throw new ArgumentNullException("The value of the type IDynamicObjectMember can not be null");
                Members[key] = value;
            }
        }
    }

    public class DynamicObjectMember : IDynamicObjectMember
    {
        public string MemberType
        {
            get;
            set;
        }

        public object Value
        {
            get;
            set;
        }

        private string _name;

        public string Name
        {
            get { return _name; }
            protected set { _name = value; }
        }
    }

    public class DataMember<TMemberType> : DynamicObjectMember, IDataMember<TMemberType>
    {

        private IList<IBehavior<TMemberType>> _behaviors;

        public TMemberType TypedMemberValue
        {
            get
            {
                return (TMemberType)Value;
            }
            set
            {
                Value = value;
            }
        }

        public IList<IBehavior<TMemberType>> Behaviors
        {
            get { if (_behaviors == null) _behaviors = new List<IBehavior<TMemberType>>(); return _behaviors; }
            protected set { _behaviors = value; }
        }
        
    }


    public class DataObject<TType> : DynamicObject, IDataObject<TType> where TType : IDomainObject
    {

        IList<IBehavior<TType>> _objectBehaviors;

        public IList<IBehavior<TType>> ObjectBehaviors
        {
            get { return _objectBehaviors; }
            protected set { _objectBehaviors = value; }
        }

        public IList<IBehavior<T>> GetDataMemberBehavior<T>(string memberKey)
        {
            return GetDataMember<T>(memberKey).Behaviors;
        }

        public IDataMember<T> GetDataMember<T>(string memberKey)
        {
            return Members[memberKey] as IDataMember<T>;
        }
    }

    public class DataConfiguration : IDataConfiguration
    {

        Dictionary<Type, object> _objectDict;

        protected Dictionary<Type, object> ObjectDict
        {
            get
            {
                if (_objectDict == null)
                    _objectDict = new Dictionary<Type, object>();
                return _objectDict;
            }
        }

        public void Set<TType>(IDataObject<TType, string> dataObject) where TType : IDomainObject
        {
            ObjectDict.Add(typeof(TType), dataObject);
        }

        public IDataObject<TType, string> Get<TType>() where TType : IDomainObject
        {
            return ObjectDict[typeof(TType)] as IDataObject<TType, string>;
        }

        public void AddObjectBehavior<TObjectType>(IBehavior<TObjectType> behavior) where TObjectType : IDomainObject
        {
            Get<TObjectType>().ObjectBehaviors.Add(behavior);
        }
    }



}
